package com.inter.controller.asyncorder;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.inter.config.StringOutputConstant;
import com.inter.entity.agatewaytobeijing.JsonConstant;
import com.inter.entity.agatewaytobeijing.end.response.EndResponse;
import com.inter.entity.agatewaytobeijing.order.RequestPurchaseService;
import com.inter.entity.agatewaytobeijing.order.response.OrderResponse;
import com.inter.entity.agatewaytobeijing.querydevice.beijing.response.ResponseQueryDevice;
import com.inter.entity.agatewaytobeijing.querydeviceorder.response.DevicePackageOrder;
import com.inter.entity.agatewaytobeijing.querydeviceorder.response.ResponseQueryDeviceOrder;
import com.inter.entity.common.PartnerProductPackage;
import com.inter.entity.interentity.travisorder.request.RequestOrderData;
import com.inter.entity.interentity.travisorder.request.RequestOrderTradeData;
import com.inter.entity.interentity.travisorder.request.RequestTravisOrder;
import com.inter.entity.interentity.travisorder.response.ResponseOrderData;
import com.inter.entity.interentity.travisorder.response.ResponseOrderTradeData;
import com.inter.entity.interentity.utils.UtilsInterfacesPackage;
import com.inter.service.OrderPaymentManagerService;
import com.inter.service.PartnerService;
import com.inter.service.SequenceService;
import com.inter.service.agatewaytobeijing.GatewayToBeijingService;
import com.inter.service.impl.AsyncOrderPlanService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiParam;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;

import java.text.SimpleDateFormat;
import java.util.Date;

/**
 * 订购套餐 ：专用于travis
 * <p>
 * 此接口用于支付之后来通知领科为某卡片真的订购套餐
 * <p>
 * 1，订购套餐之前先查询下设备上是否有正在使用的订单
 * 2，有正在使用的订单的话一定要先提前结束正在使用的订单
 * 3，订购套餐，就是发起一次下新单的请求。
 * 4，等到结果回来再返回。
 *
 * @author lm
 * @date 2020/03/25
 * @date 2021/05/26 最近一次修改的时间
 */
@RestController
@Api(tags = "异步：订购套餐")
@Slf4j
public class AsyncOrderServicePlanController {
    @Autowired
    private SequenceService sequenceService;
    @Autowired
    OrderPaymentManagerService orderService;
    @Autowired
    AsyncOrderPlanService asyncOrderService;
    @Autowired
    PartnerService partnerService;
    @Autowired
    GatewayToBeijingService toBeijingService;

    @CrossOrigin
    @PostMapping(value = "asyncOrderPackage", produces = "application/json;charset=utf-8")
    @ResponseBody
    @ApiOperation(value = "订购套餐", response = ResponseOrderData.class)
    public String asyncOrderServicePlan(@ApiParam @RequestBody RequestTravisOrder order) {
        // 1，生成流水号
        String connSeqNo = sequenceService.getPackageTaskNo();
        // 2,生成当前时间戳
        SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        String curTime = df.format(new Date());

        UtilsInterfacesPackage utils = new UtilsInterfacesPackage();
        String requestStr = JSON.toJSONString(order);

        if (StringUtils.isBlank(requestStr)) {
            return utils.dataWeiKong(connSeqNo, curTime);
        }
        log.info("前端请求报文是：" + requestStr);
        RequestTravisOrder request = JSONArray.parseObject(requestStr, RequestTravisOrder.class);
        if (StringUtils.isBlank(request.getSign())) {
            return utils.dataWeiKong(connSeqNo, curTime);
        }
        if (null == request.getData()) {
            return utils.dataWeiKong(connSeqNo, curTime);
        }
        // 将请求体json转成String
        String str = JSON.toJSONString(request.getData());
        // 将Str拿去计算签名
        String sign = utils.calculateSignature(str);
        if (!request.getSign().equalsIgnoreCase(sign)) {
            return utils.errSignature(connSeqNo, curTime);
        }
        /*签名验证通过，验证data里面的参数*/
        RequestOrderData requestData = request.getData();
        if (StringUtils.isBlank(requestData.getConnSeqNo()) || StringUtils.isBlank(requestData.getPartnerCode()) || StringUtils.isBlank(requestData.getToken()) || StringUtils.isBlank(requestData.getTradeType()) || StringUtils.isBlank(requestData.getTradeTime()) || StringUtils.isBlank(requestData.getLang()) || null == requestData.getTradeData()) {
            return utils.dataWeiKong(connSeqNo, curTime);
        }
        RequestOrderTradeData tradeData = requestData.getTradeData();
        if (StringUtils.isBlank(tradeData.getDeviceId()) || StringUtils.isBlank(tradeData.getPackageCode()) || StringUtils.isBlank(tradeData.getOrderPeriod()) || StringUtils.isBlank(tradeData.getAmount()) || StringUtils.isBlank(tradeData.getCurrency()) || StringUtils.isBlank(tradeData.getRequestOrderId())) {
            return utils.dataWeiKong(connSeqNo, curTime);
        }
        /*还是需要判断一下数据库里面是不是已经有这条请求下单的记录了*/
        Integer count = orderService.findDataByRequestOrderId(tradeData.getRequestOrderId(), tradeData.getDeviceId(), tradeData.getOrderPeriod(), requestData.getPartnerCode(), tradeData.getPackageCode());
        if (count > 0) {
            log.info("重复请求！");
            return utils.duplicateRequestMessage(requestData.getConnSeqNo(), requestData.getPartnerCode(), requestData.getTradeTime(), requestData.getToken(), requestData.getTradeType());
        }
        /*查询数据库里面有咩有当前企业能不能购买此套餐*/
        PartnerProductPackage pa = orderService.queryPackageByCode(requestData.getPartnerCode(), tradeData.getPackageCode());
        if (null == pa) {
            log.info("未查询到partnerCode对应的packageCode！");
            return utils.unableOrder(requestData.getConnSeqNo(), requestData.getPartnerCode(), requestData.getTradeTime(), requestData.getToken(), requestData.getTradeType());
        }
        String secret = partnerService.findSecretByPartnerCode(requestData.getPartnerCode());
        if (StringUtils.isBlank(secret)) {
            log.info("企业对应的secret有误");
            return utils.unableOrder(requestData.getConnSeqNo(), requestData.getPartnerCode(), requestData.getTradeTime(), requestData.getToken(), requestData.getTradeType());
        }
        /*先去验证卡片的有效性，如果卡片无效就不允许下单*/
        ResponseQueryDevice device = toBeijingService.queryDevice(tradeData.getDeviceId(), requestData.getPartnerCode(), secret);
        boolean b3 = null == device || null == device.getCode() || null == device.getData() || StringUtils.isBlank(device.getData().getLifecycle()) || "null".equalsIgnoreCase(device.getData().getLifecycle()) ||
                (StringUtils.isNotBlank(device.getData().getLifecycle()) && (device.getData().getLifecycle().equals(StringOutputConstant.CODE_FOUR) || device.getData().getLifecycle().equals(StringOutputConstant.CODE_FIVE)));
        if (b3) {
            log.info("【iccId验证】SIM卡已过期");
            return utils.invalidUnableOrder(connSeqNo, requestData.getPartnerCode(), requestData.getToken(), curTime, requestData.getTradeType());
        }

        /*先去数据库记录此条订购套餐记录*/
        Integer co = asyncOrderService.storageOrderPayment(pa.getPartnerCode(), pa.getPartnerName(), pa.getPackageCode(), pa.getPackageName(), pa.getPackageType(),
                tradeData.getDeviceId(), tradeData.getOrderPeriod(), tradeData.getAmount(), tradeData.getCurrency(), tradeData.getRequestOrderId());
        if (co < 1) {
            log.info("下单记录入库失败，应该要返回！");
            return utils.systemAbnormal(requestData.getConnSeqNo(), requestData.getPartnerCode(), requestData.getTradeTime(), requestData.getToken(), requestData.getTradeType());
        }

        log.info("下单记录入库成功，继续");
        /*查询正在使用的订单*/
        ResponseQueryDeviceOrder orderQuery = toBeijingService.queryDeviceOrder(tradeData.getDeviceId(), "", "2", "", pa.getPartnerCode(), secret);
        if (null != orderQuery && JsonConstant.RET_CODE_0000.equals(orderQuery.getCode()) && null != orderQuery.getData() && null != orderQuery.getData().getPackageOrder() && !orderQuery.getData().getPackageOrder().isEmpty()) {
            for (DevicePackageOrder or : orderQuery.getData().getPackageOrder()) {
                if (StringUtils.isNotBlank(or.getOrderId()) && StringOutputConstant.CODE_TWO.equals(or.getOrderStatus()) && !"DP20190513000751".equals(or.getPackageCode())) {
                    /*开始对正在使用的订单进行提前结束*/
                    EndResponse aheadFinish = toBeijingService.aheadEndOrder(or.getOrderId(), pa.getPartnerCode(), secret, "周期未结束需开启新的订单");
                    /*成功提前结束的情况*/
                    if (null != aheadFinish) {
                        if (null != aheadFinish.getCode()) {
                            if (JsonConstant.RET_CODE_0000.equals(aheadFinish.getCode())) {
                                /*成功提前结束订单*/
                                log.info(tradeData.getDeviceId() + ":提前结束订单：" + or.getOrderId() + "：成功！");
                            } else {
                                //发送异常邮件：
                                asyncOrderService.SendMail(tradeData.getDeviceId(), pa.getPackageName(), or.getOrderId(), "提前结束订单", aheadFinish.getMessage());
                                log.info(tradeData.getDeviceId() + "：【正在使用订单】提前结束失败，原因：" + aheadFinish.getMessage());
                            }

                        } else {
                            log.info(tradeData.getDeviceId() + ":提前结束订单：" + or.getOrderId() + "：失败！");
                            /*接口响应原因导致的提前结束订单失败：发送异常邮件*/
                            asyncOrderService.SendMail(tradeData.getDeviceId(), pa.getPackageName(), or.getOrderId(), "提前结束订单", "接口连接超时或其他原因的提前结束失败");
                            //记录异常操作到数据库：
                            log.info(tradeData.getDeviceId() + "：【正在使用订单】因接口连接超时或其他原因提前结束失败");
                        }
                    } else {
                        log.info(tradeData.getDeviceId() + ":提前结束订单：" + or.getOrderId() + "：失败！");
                        /*接口响应原因导致的提前结束订单失败：发送异常邮件*/
                        asyncOrderService.SendMail(tradeData.getDeviceId(), pa.getPackageName(), or.getOrderId(), "提前结束订单", "接口连接超时或其他原因的提前结束失败");
                        //记录异常操作到数据库：
                        log.info(tradeData.getDeviceId() + "：【正在使用订单】因接口连接超时或其他原因提前结束失败");
                    }

                }
            }
        }
        log.info("不管提前结束订单有没有执行，继续往下去做订购套餐操作");
        /*组装订购数据*/
        RequestPurchaseService purchase = RequestPurchaseService.builder()
                .secret(secret).partnerCode(pa.getPartnerCode()).deviceCode(tradeData.getDeviceId())
                .packageCode(pa.getPackageCode()).packageName(pa.getPackageName()).packageType(pa.getPackageType())
                .orderPeriod(tradeData.getOrderPeriod()).amount(tradeData.getAmount()).payType("2").build();
        /*发起订购套餐*/
        ResponseOrderTradeData tr = null;
        OrderResponse orderPackage = toBeijingService.order(purchase, "0");
        /*先看接口订购套餐接口请求失败的情况*/
        if (null == orderPackage || null == orderPackage.getCode() || null == orderPackage.getData()) {
            /*发送异常邮件*/
            asyncOrderService.SendMail(tradeData.getDeviceId(), pa.getPackageName(), "", "订购流量套餐", "接口连接超时或其他原因导致订购失败");
            return utils.responseStr(9999, "Unknown abnormal", tr, requestData.getConnSeqNo(), requestData.getPartnerCode(), requestData.getToken(), requestData.getTradeType(), requestData.getTradeTime());
        }
        /*现在看code返回不是0000成功的情况*/
        if (!JsonConstant.RET_CODE_0000.equals(orderPackage.getCode())) {
            log.info(tradeData.getDeviceId() + ":订购套餐：" + pa.getPackageName() + ":失败！");
            /*发送异常邮件*/
            asyncOrderService.SendMail(tradeData.getDeviceId(), pa.getPackageName(), "", "订购流量套餐", orderPackage.getMessage());
            //设备当前状态不允许订购流量套餐
            if (StringOutputConstant.CODE_0022.equals(orderPackage.getCode())) {
                return utils.responseStr(22, "The current state of the device does not allow you to order a data plan", tr, requestData.getConnSeqNo(), requestData.getPartnerCode(), requestData.getToken(), requestData.getTradeType(), requestData.getTradeTime());
            } //不允许此合作伙伴的设备订购该流量套餐；
            else if (StringOutputConstant.CODE_0023.equals(orderPackage.getCode())) {
                return utils.responseStr(23, "This partner's device is not allowed to order the data package", tr, requestData.getConnSeqNo(), requestData.getPartnerCode(), requestData.getToken(), requestData.getTradeType(), requestData.getTradeTime());

            } //订购周期不合法，不能订购；
            else if (StringOutputConstant.CODE_0024.equals(orderPackage.getCode())) {
                return utils.responseStr(24, "The ordering period is illegal and cannot be ordered", tr, requestData.getConnSeqNo(), requestData.getPartnerCode(), requestData.getToken(), requestData.getTradeType(), requestData.getTradeTime());

            } //开通标识不合法，不能订购；
            else if (StringOutputConstant.CODE_0025.equals(orderPackage.getCode())) {
                return utils.responseStr(25, "Open the logo is not legal, can not order", tr, requestData.getConnSeqNo(), requestData.getPartnerCode(), requestData.getToken(), requestData.getTradeType(), requestData.getTradeTime());

            } //订购周期不合法，不能订购；
            else if (StringOutputConstant.CODE_0009.equals(orderPackage.getCode())) {
                return utils.responseStr(9, "No equipment", tr, requestData.getConnSeqNo(), requestData.getPartnerCode(), requestData.getToken(), requestData.getTradeType(), requestData.getTradeTime());

            } //开通标识不合法，不能订购；
            else if (StringOutputConstant.CODE_0010.equals(orderPackage.getCode())) {
                return utils.responseStr(10, "Device information does not exist", tr, requestData.getConnSeqNo(), requestData.getPartnerCode(), requestData.getToken(), requestData.getTradeType(), requestData.getTradeTime());

            } else {
                return utils.responseStr(9998, "Other exceptions caused the order to fail", tr, requestData.getConnSeqNo(), requestData.getPartnerCode(), requestData.getToken(), requestData.getTradeType(), requestData.getTradeTime());
            }
        }

        /*看接口请求正常的情况*/
        if (StringUtils.isBlank(orderPackage.getData().getOrder_id())) {
            /*虽然下单的结果是成功的，但是orderId是非法值也不能作为成功的下单*/
            /*发送异常邮件*/
            asyncOrderService.SendMail(tradeData.getDeviceId(), pa.getPackageName(), "", "订购流量套餐", "订购成功但接口返回order_id为空");
            log.info(tradeData.getDeviceId() + ":订购套餐：" + pa.getPackageName() + "：获取订单：" + orderPackage.getData().getOrder_id() + ":为空！");
            return utils.responseStr(1140, "The order failed for unknown reasons", tr, requestData.getConnSeqNo(), requestData.getPartnerCode(), requestData.getToken(), requestData.getTradeType(), requestData.getTradeTime());
        }
        /*订购套餐成功获取到orderId*/
        log.info(tradeData.getDeviceId() + ":订购套餐：" + pa.getPackageName() + "：获取订单：" + orderPackage.getData().getOrder_id() + ":成功！");
        //先去更新数据库将orderId插入进去
        Integer ct = asyncOrderService.updateOrderId(orderPackage.getData().getOrder_id(), tradeData.getDeviceId(), requestData.getPartnerCode(), pa.getPackageCode(), tradeData.getRequestOrderId());
        if (ct > 0) {
            log.info(orderPackage.getData().getOrder_id() + ":数据库更新成功！");
            /*有成功的orderId并且成功的在数据库更新了*/
            tr = new ResponseOrderTradeData();
            tr.setDeviceId(tradeData.getDeviceId());
            tr.setOrderId(orderPackage.getData().getOrder_id());
            return utils.responseStr(1000, "success", tr, requestData.getConnSeqNo(), requestData.getPartnerCode(), requestData.getToken(), requestData.getTradeType(), requestData.getTradeTime());
        }
        log.info(orderPackage.getData().getOrder_id() + ":数据库更新失败！");
        return utils.responseStr(1140, "The order failed for unknown reasons", tr, requestData.getConnSeqNo(), requestData.getPartnerCode(), requestData.getToken(), requestData.getTradeType(), requestData.getTradeTime());
    }

}